package elements;

import java.util.Map;
import java.util.Set;


import gui.Facade;
import roborally.Board;
import roborally.Position;
/**
 * @invar	| this.getBoard() == null || this.getPosition()!=null
 * 
 * @version	3.0
 * @author 	Lies Tambeur 	r0264469	2Bcwsbbh
 * @author	Eline Vanrykel	r0264543	2Bcwselt
 *
 */
public abstract class Element extends Terminatable{

	protected Element(){
	}
	
	public abstract void hit();
	
	/**
	 * @param 	other
	 * @return	| if (other instanceof Wall || this instanceof Wall) 
	 * 			|		then result == false
	 *			| else if (other instanceof Robot || this instanceof Robot) 
	 * 			|		then result == false
	 *			| else result == true
	 */
	public boolean canSharePositionWith(Element other){
		if (other instanceof Wall || this instanceof Wall) {
			return false;
		}
		if (other instanceof Robot && this instanceof Robot) {
			return false;
		}
		return true;
	}
	
	/**
	 * @return	| Facade.getBoard().contains(result) && result.getElements(this.getPosition()).contains(this)
	 */
	public Board getBoard(){ 
		Set<Board> boards = Facade.getBoards();	
		java.util.Iterator<Board> it = boards.iterator();
		Board theBoard = null;
		boolean insertion = false;
		while(it.hasNext() && !insertion){
			Board itBoard = it.next();
			java.util.Iterator<Element> elementsOnItBoard = itBoard.getAllElements().iterator();
			while(elementsOnItBoard.hasNext() && !insertion){
				Element curElement = elementsOnItBoard.next();
				if(curElement.equals(this)){
					theBoard = itBoard;
					insertion = true;
				}					
			}
		}
		return theBoard;
	}
	
	/**
	 * @throws 	IllegalStateException
	 * 			| this.getBoard() == null
	 * @return	| this.getBoard().getAllPositionsInUse().contains(result) && this.getBoard().getElements(result).contains(this)
	 */
	public Position getPosition() throws IllegalStateException{
		if(this.getBoard()==null){
			throw new IllegalStateException();
		}
		else{
			Map<Position,Set<Element>> elements = this.getBoard().getElements();
			Set<Position> positions = elements.keySet();
			java.util.Iterator<Position> itPosition = positions.iterator();
			while(itPosition.hasNext()){
				Position position = itPosition.next();
				Set<Element> elementsInPosition = elements.get(position);
				java.util.Iterator<Element> itElement = elementsInPosition.iterator();
				while(itElement.hasNext()){
					Element element = itElement.next();
					if(element==this){
						return position;
					}
				}
			}
			return null; //should be impossible to reach
		}
	}

	/**
	 * @post	| this.isTerminated() 
	 * @post	| for each board in Facade.getBoards():
	 * 			|	!board.getAllElements().contains(this)
	 */
	@Override
	public void terminate(){
		if(this.getBoard()!=null){
			this.getBoard().removeElement(this);
		}
		this.setTerminate();
	}
	
}
